/************************************************************************
This file is part of Polar4linux
Copyright (C) 2010-2011 Eric jrdn2
Portions Copyright (C) 2007 Matti Juvonen <mpj@iki.fi> (RS400 Tools)
Portions Copyright (C) 2006 Jani Hursti <jani.hursti@hut.fi>,
Portions Copyright (C) 2001-2003 Tom Oliveira e Silva

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
************************************************************************/

#ifndef _RS400_STRUCT_H
#define _RS400_STRUCT_H

#define RS400_MAX_PACKET_SIZE 32768
#define RS400_CMD_FACTORYRESET 0x09
#define RS400_CMD_WATCHMODE 0x0a
#define RS400_CMD_GETOVERVIEW 0x15
#define RS400_CMD_CONTINUEXFER 0x16
#define RS400_CMD_SLEEPMODE 0x69
#define RS400_CMD_GETSESSION 0x6a

#define ADVANCEDEX 0
#define TRAININGEX 1

#include <string>
#include <vector>
#include <cstring>

class polarLINUXio_user
{
	public:
	polarLINUXio_user():weight(0),height(0),birth_day(0),birth_month(0),birth_year(0),
	FCmax(0),VO2max(0),FCmin(0),sex(0),activity_level(0){};
	
	unsigned int  weight; //weight is in lbs multiplied b 10
	unsigned char height; //height is in cms
	unsigned char birth_day;
	unsigned char birth_month;
	unsigned char birth_year;
	unsigned char FCmax;
	unsigned char VO2max;
	unsigned char FCmin;
	unsigned char sex; //male=1, female=0
	unsigned char activity_level;//0=Top, 1=High, 2=Moderate, 3=low	
};

class polarLINUXio_player
{
	public:
	polarLINUXio_player():player_number(0)
	{
		memcpy(first_name,"\0\0\0\0\0\0\0\0\0\0\0",11);
		memcpy(last_name,"\0\0\0\0\0\0\0\0\0\0\0",11);
	};
	unsigned char player_number; 
	unsigned char first_name[10+1]; //10 real char + '\0'
	unsigned char last_name[10+1];  //10 real char + '\0'
};


class polarLINUXio_display
{
	public:
	polarLINUXio_display():display1up(0),display1middle(0),display1down(0),
	display2up(0),display2middle(0),display2down(0),
	display3up(0),display3middle(0),display3down(0),
	display4up(0),display4middle(0),display4down(0),
	display5up(0),display5middle(0),display5down(0),
	display6up(0),display6middle(0),display6down(0),
	display2activated(0),display3activated(0),display4activated(0),display5activated(0),display6activated(0){};

	//possible values for display:
	// 01=HR 02=duration, 03=intermediate time, 04=pace 05=speed 06=distance 07=hour, 08=sportzone intervals,
	// 09=interval???, 0A=sportzone interval, 0B=calories, 0C=time to go, 0D=distance to go, 0E sportzone intervals
	unsigned char display1up,display1middle,display1down; 
	unsigned char display2up,display2middle,display2down;
	unsigned char display3up,display3middle,display3down;
	unsigned char display4up,display4middle,display4down;
	unsigned char display5up,display5middle,display5down;
	unsigned char display6up,display6middle,display6down;
	
	//activation: 1=yes, 0=no
	unsigned char display2activated,display3activated,display4activated,display5activated,display6activated;
};

class polarLINUXio_event
{
	public:
	polarLINUXio_event():isActive(false),numdays(0){eventName[0]='\0';};
	bool isActive;
	int numdays; //when, expressed in day after today
	unsigned char eventName[10+1];
};

class polarLINUXio_general_settings
{
	public:
		polarLINUXio_general_settings():sh1km(0),sh2km(0),calibration(0),sampleRate(0),autolap(0),speedOrPace(0),
		autolapDistance(0),HRFormat(0),estimatedFCMax(0),measureSpeed(0),shoes(0),lockON(0),lockONpaceValue(0),
		units(0),showScreenName(0),autoLock(0),zoneWarning(0),optionsLock(0),bipButton(0),language(0),hearttouch(0),
		day(0),month(0),year(0),second(0),minute(0),hour(0),
		display12h(0),shift_fuse2(0),wakeUpMin(0),wakeUpHour(0),wakeUpOn(0),
		hoursTotal(0),minutesTotal(0),caloriesTotal(0),Totaldistance(0),exerciseTotal(0)
		{
		memcpy(sh1,"\0\0\0\0\0\0\0\0\0\0",10);
		memcpy(sh2,"\0\0\0\0\0\0\0\0\0\0",10);
		memcpy(sh1date,"\1\1\1",3);
		memcpy(sh2date,"\1\1\1",3);
		memcpy(dateTotalDuration,"\1\1\1",3);
		memcpy(dateTotalExercises,"\1\1\1",3);
		memcpy(dateTotalCalories,"\1\1\1",3);
		memcpy(dateTotaldistance,"\1\1\1",3);
		memcpy(dateshoes1,"\1\1\1",3);
		memcpy(dateshoes2,"\1\1\1",3);
		memcpy(sportZvalues,"\0\0\0\0\0\0",6);
		};

//general settings 0
	unsigned char sh1[9+1];//shoes1 name
	unsigned char sh2[9+1];//shoes2 name
	unsigned int sh1km; //number of kilometers of shoes 1
	unsigned int sh2km; //number of kilometers of shoes 2
	unsigned char sh1date[3]; //date for shoes 1
	unsigned char sh2date[3]; //date for shoes 2

	unsigned int calibration;//calibration coefficient of the footpod *1000
	unsigned char sampleRate; //0=1s, 1=5s, 2=15s, 3=60s
	unsigned int autolap;//(autolap=1; no autolap=0)
	unsigned int speedOrPace;//(pace=0, speed=1)
	unsigned char autolapDistance; //==1 km .should it be converted???
	unsigned char HRFormat; //0=absolute, 1 HRMaxpercent
	unsigned char estimatedFCMax; //1 true, 0 false
	unsigned int measureSpeed;//footpod (1) or not
	unsigned char shoes; //(first pair=0; second pair=1
	unsigned char lockON; //01=pace, 00=sportzone
	unsigned char lockONpaceValue; //+-pace value (seconds) for mode locking

//general settings 1
	unsigned int units;//1=lb 0=kg
	unsigned int showScreenName; //0 no show, 1 show
	unsigned int autoLock; //0 noautolock, 1 autolock
	unsigned int zoneWarning;//1 nozone warning, 0 zonewarning !!!!!!!!!
	unsigned int optionsLock;  //0 nooptionsLock, 1 optionlock
	unsigned char bipButton; //0=silent, 1=bip
	unsigned char language; //00=english, 01=german, 02=spanish, 03=french 04=spanish??
	unsigned char hearttouch; //5=inutilise, 4=light, 3=changer affichage, 2=enr. lap, 1=zone;

	polarLINUXio_display displaywoSpeed; //displays when speed measurement are not done
	polarLINUXio_display displaywSpeed; //displays when speed measurement are done
	
//general settings 3 : time
	unsigned char day;
	unsigned char month;
	unsigned char year;
	unsigned char second;
	unsigned char minute;
	unsigned char hour;

	unsigned char display12h; //set to 1 to display12h, zero to display 24h
	unsigned char shift_fuse2; //jet lag for the other time display !!!signed!!!
	unsigned char wakeUpMin;
	unsigned char wakeUpHour;
	unsigned char wakeUpOn; //0=no, 1=once, 2=monday to friday, 3=everyday
	polarLINUXio_event event; //event is dependant from the date so is now in general settings
	
//general settings : statistics
	unsigned int hoursTotal;
	unsigned int minutesTotal;
	unsigned int  caloriesTotal;
	unsigned int  Totaldistance;

	//unsigned char caloriesTotal1;
	//unsigned char caloriesTotal2;//a grouper 1 et 2
	unsigned int exerciseTotal; 
	//ascension?????????
	unsigned char dateTotalDuration[3];//dd mm yy
	unsigned char dateTotalExercises[3];
	unsigned char dateTotalCalories[3];
	unsigned char dateTotaldistance[3];
	unsigned char dateshoes1[3];
	unsigned char dateshoes2[3];

	//sportzones
	unsigned int sportZvalues[6];
};

class polarLINUXio_basic_exercise
{
	public:
	polarLINUXio_basic_exercise():number(0),num_zones(0),active_zonesTargets(0),guideType(0),zones_type(0),
	zone1length(0),zone2length(0),zone3length(0)
	{
		memcpy(name,"\0\0\0\0\0\0\0\0\0\0\0",11);
		memcpy(description,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",21);
		memcpy(FC1min,"\0\0",2);
		memcpy(FC2min,"\0\0",2);
		memcpy(FC3min,"\0\0",2);
		memcpy(FC1max,"\0\0",2);
		memcpy(FC1max,"\0\0",2);
		memcpy(FC1max,"\0\0",2);
	}
	
	unsigned char number;
	unsigned char name[10+1];
	unsigned char description[20+1];
	unsigned char num_zones; //number of zones, up to 3
	unsigned char active_zonesTargets; //
	unsigned char guideType; //01=time guide, 02=distance guide, 00 none
	unsigned char zones_type; //0x00=Nothing, 0x04=HR free, 0x14=HRtargets, 0x15=%HRtarget 0x1C=ownzone, 0x18=sportzone, 0x24=speed, 0x34=pace

	int zone1length; 
	int zone2length;
	int zone3length;

	unsigned char FC1min[2];
	unsigned char FC2min[2];
	unsigned char FC3min[2];

	unsigned char FC1max[2];
	unsigned char FC2max[2];
	unsigned char FC3max[2];
};

class polarLINUXio_exercises_list
{
	public:
	polarLINUXio_exercises_list():totalnum(0){};
	
	polarLINUXio_basic_exercise exo[10];
	char totalnum;
};


class phase
{
	public:
	phase():durationtype(1),guidetype(0x04),repeatNUM(1),repeatWhat(0),duration1(0),duration2(0)
	{
		memcpy(phasename,"\0\0\0\0\0\0\0\0\0\0\0",11);
		memcpy(FClow,"\0\0",2);
		memcpy(FCHigh,"\0\0",2);
	}

	unsigned char phasename[11];
	unsigned char durationtype; //=01;//1=manual,2=hour,3 distance,4=inc FC, 5=dec FC .......+8 guives manual start
	unsigned char guidetype; // = 0x15; //0x15=HR,0x04=free,0x18=sportZone,0x34=pace,0x24=speed 
	unsigned char repeatNUM; //=01;//repeat n times
	unsigned char repeatWhat; //=01;//repeat starting from which phase? (equals to 0 for self)
	unsigned char duration1; //=15; //minutes
	unsigned char duration2; //=10; //seconds
	//unsigned char FCrange[2]; //={65,85}; //{0,0} for free style
	unsigned char FClow[2]; //={65,00};
	unsigned char FCHigh[2]; //={85,00}; //high element is divided by 255 to give tenths, for speed. For pace, 1s/km=10.f
};

class polarLINUXio_advancedExo
{
	public:
		polarLINUXio_advancedExo():hour(0),minute(0),numPhases(0)
		{
			memcpy(name,"\0\0\0\0\0\0\0\0\0\0\0",11);
			memcpy(desc,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",21);
			memcpy(desc2,"\0\0\0\0\0\0\0\0\0\0\0",11);
			memcpy(date,"\1\1\1",3);
		}
	unsigned char name[10+1];
	unsigned char desc[20+1];
	unsigned char desc2[10+1];
	unsigned char date[3];
	unsigned char hour;
	unsigned char minute;
	unsigned char numPhases;
	phase p[12];
};


class polarLINUXio_advanced_exercises_list
{
	public:
	polarLINUXio_advanced_exercises_list():maximumNumberOfExercises(0){};
	~polarLINUXio_advanced_exercises_list(){exo.clear();}
	unsigned int size()const {return exo.size();}
	std::vector<polarLINUXio_advancedExo> exo;
	unsigned int maximumNumberOfExercises;
};

class polarLINUXio_reminder
{
	public:
		polarLINUXio_reminder():remindAt(0),repeatMode(0),bipstyle(0),repeatExercise(0),active(0)
		{
			memcpy(date,"\1\1",2);
			memcpy(time,"\0\0",2);
			memcpy(name,"\0\0\0\0\0\0\0\0\0\0\0",11);
		}
	unsigned char date[2];
	unsigned char time[2];
	unsigned char name[10+1];
	unsigned char remindAt;//8=1hour, 4=30min, 2=10min, 0=on time
	unsigned char repeatMode;//repeatmode:01=1 fois,02=horaire, 03=quotidien, 04=hebdo, 05=mensuel, 06=annuel
	unsigned char bipstyle;//repeatstyle: 0x80=normal, 0x20=silent, 0x40=sound
	unsigned char repeatExercise;//repeatExercise:0x00 none, 0x10: free, 0x2p=basicEx #p, 0x4p=advancedEx #p
	unsigned char active; //is active or not
};

class polarLINUXio_reminders
{
	public:
	polarLINUXio_reminder rem[7];
};


class rs400_sample
{
	public:
		rs400_sample():hr(0),speed(0){};

    unsigned int hr;
    unsigned int speed;
};

class rs400_lap
{
	public:
	rs400_lap():lap_no(0),lap_end_time(0),/*laptime(0),*/autolap(0),
	hr_end(0),hr_avg(0),hr_max(0),hr_min(0),pace_end(0),pace_avg(0),distance(0),laptype(0)
	{
		memset(note,'\0',40);
		memset(lapname,'\0',40);
	};

	unsigned int lap_no;
	double lap_end_time;
	double laptime;
	char autolap;
	unsigned int hr_end;
	unsigned int hr_avg;
	unsigned int hr_max;
	unsigned int hr_min;
	unsigned int pace_end;
	unsigned int pace_avg;
	unsigned int distance;
	unsigned int laptype; //0 for regular lap, 33554432 for exercise phase
	char note[40];
	char lapname[40];
};
bool operator < (const rs400_lap &l1,const rs400_lap &l2);

//unused!?!
class rs400_limiterzone
{
	public:
		rs400_limiterzone():limit_low(0),limit_high(0),sport_zone(0),below_zone_seconds(0),on_zone_seconds(0),above_zone_seconds(0){};

    unsigned int limit_low;
    unsigned int limit_high;
    unsigned int sport_zone; /* what is this? */
    double below_zone_seconds;
    double on_zone_seconds;
    double above_zone_seconds;
};

class rs400_selection
{
	public:
	rs400_selection():low(0),high(0){};
	
	unsigned int low;
	unsigned int high;
};

class rs400_session
{
	public:
	rs400_session():limit_type(0),has_pace_data(0),number_of_phases(0),total_number_of_intervals(0),number_of_laps(0),
	number_of_samples(0),day(0),month(0),year(0),start_hour(0),start_minute(0),start_second(0),duration(0),
	hr_avg(0),hr_max(0),hr_min(0),user_weight(0),user_hr_max(0),user_hr_rest(0),user_vo2_max(0),calories(0),
	si_units(0),distance(0),pace_max(0),pace_avg(0),best_lap(0),best_laptime(0),recording_interval(0),refCount(0)
	{
		memset(id,'\0',31);
		memset(name,'\0',9);
		memset(comment,'\0',250);
	}
	
	void reset()
	{
		limit_type=0;has_pace_data=0;number_of_phases=0;total_number_of_intervals=0;number_of_laps=0;
		number_of_samples=0;day=0;month=0;year=0;start_hour=0;start_minute=0;start_second=0;duration=0;
		hr_avg=0;hr_max=0;hr_min=0;user_weight=0;user_hr_max=0;user_hr_rest=0;user_vo2_max=0;calories=0;
		si_units=0;distance=0;pace_max=0;pace_avg=0;best_lap=0;best_laptime=0;recording_interval=0;
		memset(id,'\0',31);
		memset(name,'\0',9);
		memset(comment,'\0',250);
		lap.clear();
		sample.clear();
		selections.clear();
		filename.clear();
	}
	
	char id[31];
	unsigned char name[9];
	unsigned char limit_type;
	unsigned int has_pace_data;
	unsigned int number_of_phases; //new, nov 16 2011
	unsigned int total_number_of_intervals; //new, nov 16 2011: number of phase multiplied by number of repeats
	unsigned int number_of_laps;
	unsigned int number_of_samples;
	unsigned int day;
	unsigned int month;
	unsigned int year;
	unsigned int start_hour;
	unsigned int start_minute;
	unsigned int start_second;
	double duration;
	unsigned int hr_avg;
	unsigned int hr_max;
	unsigned int hr_min;
	unsigned int user_weight;
	unsigned int user_hr_max;
	unsigned int user_hr_rest;
	unsigned int user_vo2_max;
	unsigned int calories;
	unsigned int si_units; /* true = kg/cm/km */
	unsigned int distance;
	unsigned int pace_max;
	unsigned int pace_avg;
	unsigned int best_lap;
	double best_laptime;
	unsigned int recording_interval;

	unsigned int sportzone[6];

	rs400_limiterzone limiterzone[3];

	std::vector<rs400_lap> lap;
	std::vector<rs400_sample> sample;
	std::vector<rs400_selection> selections; //selected ranges
	
	char comment[250]; //ej
	
	//internals:
	std::string filename;
	bool has_changed;
	int refCount;
};
bool operator == (const rs400_session &s1,const rs400_session &s2);

/*
typedef struct {
    unsigned short value;
    unsigned short recorded_day;
    unsigned short recorded_month;
    unsigned int recorded_year;
} rs400_ownIndex;
*/

class rs400_overview
{
	public:
	rs400_overview():number_of_sessions(0),pcFreeMem(0){};
  unsigned int number_of_sessions;
	unsigned int pcFreeMem;
};


class rs400_pdd_day_info
{
	public:
	rs400_pdd_day_info():fileVersionDAY(0),nbrInfoRowsDAY(0),nbrNumRowsDAY(0),nbrNumColumnsDAY(0),
	nbrTextRowsDAY(0),maxCharPerTextRowDAY(0),date(0),nbrExercises(0),restingHR(0),orthoHR(0),weight(0),sleepingHours(0),
	sleepingPattern(0),dayInfoData(0),polarOwnIndex(0),weather(0),temperature(0)
	{
		memset(row0,'\0',512);
	}

	void reset()
	{
	fileVersionDAY=0;nbrInfoRowsDAY=0;nbrNumRowsDAY=0;nbrNumColumnsDAY=0;
	nbrTextRowsDAY=0;maxCharPerTextRowDAY=0;date=0;nbrExercises=0;restingHR=0;orthoHR=0;weight=0;sleepingHours=0;
	sleepingPattern=0;dayInfoData=0;polarOwnIndex=0;weather=0;temperature=0;
	memset(row0,'\0',512);
	}
	
	unsigned int fileVersionDAY;
	unsigned int nbrInfoRowsDAY;
	unsigned int nbrNumRowsDAY;
	unsigned int nbrNumColumnsDAY;
	unsigned int nbrTextRowsDAY;
	unsigned int maxCharPerTextRowDAY;

	unsigned int date;
	unsigned int nbrExercises;
	unsigned int restingHR;
	unsigned int orthoHR;
	unsigned int weight;
	unsigned int sleepingHours;

	unsigned int sleepingPattern;
	unsigned int dayInfoData;
	unsigned int polarOwnIndex;
	unsigned int weather;
	int temperature;

	unsigned char row0[512];
};
bool operator == (const rs400_pdd_day_info &d1,const rs400_pdd_day_info &d2);


class rs400_pdd_exercise_info
{
	public:
	rs400_pdd_exercise_info():fileVersionDAY(0),nbrInfoRows(0),nbrNumRows(0),nbrNumColumns(0),nbrTextRows(0),maxCharPerTextRow(0),
	startTime(0),totalTime(0),sport(0),distanceOLD(0),feeling(0),recovery(0),energy(0),
	totalExertion(0),zone0Time(0),zone1Time(0),zone2Time(0),zone3Time(0),zone4Time(0),
	zone5Time(0),zone6Time(0),zone7Time(0),zone8Time(0),zone9Time(0),
	zone0Exertion(0),zone1Exertion(0),zone2Exertion(0),zone3Exertion(0),zone4Exertion(0),zone5Exertion(0),
	zone6Exertion(0),zone7Exertion(0),zone8Exertion(0),zone9Exertion(0),
	recordingRate(0),HRaverage(0),HRmax(0),speedAverage(0),speedMax(0),cadenceAverage(0),cadenceMax(0)
	{
		memset(exoName,'\0',512);
		memset(exoNote,'\0',512);
		memset(exoHRMfile,'\0',512);
		memset(row3,'\0',512);
	}
		
	unsigned int fileVersionDAY;
	unsigned int nbrInfoRows;
	unsigned int nbrNumRows;
	unsigned int nbrNumColumns;
	unsigned int nbrTextRows;
	unsigned int maxCharPerTextRow;
	//
	unsigned int startTime;
	unsigned int totalTime;
	unsigned int sport;
	unsigned int distanceOLD;
	unsigned int feeling;
	unsigned int recovery;
	unsigned int energy;

	unsigned int totalExertion;
	unsigned int zone0Time;
	unsigned int zone1Time;
	unsigned int zone2Time;
	unsigned int zone3Time;
	unsigned int zone4Time;
	unsigned int zone5Time;
	unsigned int zone6Time;
	unsigned int zone7Time;
	unsigned int zone8Time;
	unsigned int zone9Time;

	unsigned int zone0Exertion;
	unsigned int zone1Exertion;
	unsigned int zone2Exertion;
	unsigned int zone3Exertion;
	unsigned int zone4Exertion;
	unsigned int zone5Exertion;
	unsigned int zone6Exertion;
	unsigned int zone7Exertion;
	unsigned int zone8Exertion;
	unsigned int zone9Exertion;

	unsigned int recordingRate;
	unsigned int HRaverage;
	unsigned int HRmax;
	unsigned int speedAverage;
	unsigned int speedMax;
	unsigned int cadenceAverage;
	unsigned int cadenceMax;

	unsigned int toFinish; //TODO
	char exoName[512];
	char exoNote[512];
	char exoHRMfile[512];
	char row3[512];
	/*
	unsigned char row4[512];
	unsigned char row5[512];
	unsigned char row6[512];
	unsigned char row7[512];
	unsigned char row8[512];
	unsigned char row9[512];
	unsigned char row10[512];
	unsigned char row11[512];
	unsigned char row12[512];
	*/
};
bool operator == (const rs400_pdd_exercise_info &e1,const rs400_pdd_exercise_info &e2);

class rs400_pdd_content
{
	public:
		rs400_pdd_content():refCount(0){};
		void reset(){dayinfo.reset();exerciseinfo.clear();filename.clear();}
		
		rs400_pdd_day_info dayinfo;
		std::vector<rs400_pdd_exercise_info> exerciseinfo;
		std::string filename;
		int refCount;
};
bool operator == (const rs400_pdd_content &p1,const rs400_pdd_content &p2);

#endif
